package com.nidu.demo.user.gatewayimpl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nidu.demo.user.convertor.UserDepartmentConvertor;
import com.nidu.demo.user.gateway.UserDepartmentGateway;
import com.nidu.demo.user.mapper.UserDepartmentMapper;
import com.nidu.demo.user.mapper.dataobject.UserDepartmentDO;
import com.nidu.demo.user.model.UserDepartment;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class UserDepartmentGatewayImpl implements UserDepartmentGateway {

    private final UserDepartmentMapper mapper;

    private final UserDepartmentConvertor convertor;

    @Override
    public void bindUserDepts(Long userId, Set<Long> deptIds) {
        List<UserDepartment> bindings = deptIds.stream()
                .map(deptId -> UserDepartment.create(userId, deptId))
                .collect(Collectors.toList());
        mapper.insert(convertor.toDataObjects(bindings));
    }

    @Override
    public void rebindUserDepts(Long userId, Set<Long> deptIds) {
        removeUserDepts(userId);
        bindUserDepts(userId, deptIds);
    }

    @Override
    public void removeUserDepts(Long userId) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getUserId, userId);
        mapper.delete(wrapper);
    }

    @Override
    public void removeDeptUsers(Long deptId) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getDeptId, deptId);
        mapper.delete(wrapper);
    }

    @Override
    public void removeUsersDepts(Set<Long> userIds) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getUserId, userIds);
        mapper.delete(wrapper);
    }

    @Override
    public void removeDeptsUsers(Set<Long> deptIds) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getDeptId, deptIds);
        mapper.delete(wrapper);
    }

    @Override
    public Set<Long> getDeptIdsByUserId(Long userId) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getUserId, userId);
        List<UserDepartmentDO> deptDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(deptDOS)) {
            return new HashSet<>();
        }
        return deptDOS.stream().map(UserDepartmentDO::getDeptId).collect(Collectors.toSet());
    }

    @Override
    public Set<Long> getUserIdsByDeptId(Long deptId) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDepartmentDO::getDeptId, deptId);
        List<UserDepartmentDO> deptDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(deptDOS)) {
            return new HashSet<>();
        }
        return deptDOS.stream().map(UserDepartmentDO::getUserId).collect(Collectors.toSet());
    }

    @Override
    public Map<Long, List<UserDepartment>> getByUserIds(Set<Long> userIds) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserDepartmentDO::getUserId, userIds);
        List<UserDepartmentDO> deptDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(deptDOS)) {
            return Collections.emptyMap();
        }
        List<UserDepartment> userDepartments = convertor.toDomainObjects(deptDOS);
        return userDepartments.stream().collect(Collectors.groupingBy(UserDepartment::getUserId));
    }

    @Override
    public Map<Long, List<UserDepartment>> getByDeptIds(Set<Long> deptIds) {
        LambdaQueryWrapper<UserDepartmentDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserDepartmentDO::getDeptId, deptIds);
        List<UserDepartmentDO> deptDOS = mapper.selectList(wrapper);
        if (CollUtil.isEmpty(deptDOS)) {
            return Collections.emptyMap();
        }
        List<UserDepartment> userDepartments = convertor.toDomainObjects(deptDOS);
        return userDepartments.stream().collect(Collectors.groupingBy(UserDepartment::getUserId));
    }

    @Override
    public Set<Long> getUserIdsByDeptIds(Set<Long> deptIds) {
        Map<Long, List<UserDepartment>> userDepartmentMap = this.getByDeptIds(deptIds);
        if(userDepartmentMap.isEmpty()){
            return Collections.emptySet();
        }
        return userDepartmentMap.values().stream().flatMap(List::stream).map(UserDepartment::getUserId).collect(Collectors.toSet());
    }

}
